(function (w) {
    class DB {
        constructor(options) {
            this.options = {
                version: 2
            };
            Object.assign(this.options, options);
            this._getDBName();
            this._init();
        }
        _getDBName(){
            this.dbName = null;
            if(this.options && this.options.dbName){
                return this.dbName = this.options.dbName
            }
            let account = localStorage.getItem('account');
            let id = null;
            if(account && account.indexOf('obj-') >= 0){
                let o = JSON.parse(account.slice(4));
                id = o.id;
            }
            return this.dbName = `RS-DB-NAME-${this.options.params.source}-${this.options.params.hwkid}-${id}`;
        }
        _init(){
            if(!window.indexedDB){
                return console.warn('您的浏览器不支持IndexDB');
            }
            this.request = window.indexedDB.open(this.dbName, this.options.version);

            this.request.onsuccess = () => {
                this.db = this.request.result;
                if(this.options.onsuccess){
                    this.options.onsuccess()
                }
            }
            this.request.onupgradeneeded = event => {
                this.db = event.target.result;
                this._onsuccess().finally(() =>{
                    if(this.options.onupgradeneeded){
                        this.options.onupgradeneeded()
                    }
                })
            }
            this.request.onerror = event => {
                if(typeof  this.options.onerror === 'function'){
                    this.options.onerror(event)
                }
            }
        }
        _onsuccess(){
         return new Promise((resolve, reject) => {
             let _this = this;
             if(Array.isArray(this.options.tables)){
                 let list = this.options.tables;
                 let i = 0;
                 function d(){
                     let item = list[i];
                     _this._createDataBase(item.name, item).finally(() => {
                         i++;
                         if(i > list.length - 1){
                             resolve();
                         }else{
                             d()
                         }
                     })
                 }
                 d();
             }
         })
        }
        _store(t){
            return this.db.transaction([this.tableName], t).objectStore(this.tableName)
        }
        _recursion(list, fn){
            return new Promise((resolve, reject) => {
                if(!(typeof fn === 'function')){
                    return reject();
                }
                let arr = [];
                let i = 0;
                let len = list.length;

                function func(){
                    let item = list[i];
                    fn(item).then(e => {
                        arr.push({
                            data: item,
                            success: true,
                            event: e
                        })
                    }).catch(e => {
                        arr.push({
                            data: item,
                            success: false,
                            event: e
                        })
                    }).finally(() => {
                        i++;
                        if(i < len){
                            func()
                        }else{
                            resolve(arr)
                        }
                    })
                }
                func();
            })
        }
        _createDataBase(name, options){
            return new Promise((resolve, reject) => {
                if(!this.db.objectStoreNames.contains(name)){
                    let objectStore =  this.db.createObjectStore(name, options.storeObj || {autoIncrement: true});
                    if(options && Array.isArray(options.indexs)){
                        this.indexs = options.indexs
                        options.indexs.map(item => {
                            objectStore.createIndex(item.key, item.key, { unique: item.unique });
                        });
                        resolve()
                    }else{
                        reject('请配置indexs')
                    }
                }else{
                    reject('已经存在...')
                }
            })
        }
        connect = name => {
            return new Promise((resolve, reject) => {
                this.tableName = name;
                resolve();
            })
        }
        add = (data, key) =>{
            return new Promise((resolve, reject) => {
                let request = this._store('readwrite').add(data, key);
                request.onsuccess = e => resolve(e);
                request.onerror = e => reject(e);
            })
        }

        addList = list => {
            return this._recursion(list, this.add)
        }

        read = (id, field) => {
            return new Promise((resolve, reject) => {
                let request = null;
                if(field){
                    let index = this._store().index(field);
                    request = index.get(id)
                }else{
                    request = this._store().get(id);
                }
                request.onerror = e => reject(e);
                request.onsuccess = function( event) {
                    if (request.result) {
                        resolve(request.result)
                    } else {
                        reject(event);
                    }
                };
            })
        }
        readAll = (field, value) => {
            return new Promise((resolve, reject) => {
                let arr = [];
                if(field){
                    let index = this._store().index(field);
                    let request = index.getAll(value);
                    request.onerror = e => reject(e);
                    request.onsuccess = function( event) {
                        if (request.result) {
                            resolve(request.result)
                        } else {
                            reject(event);
                        }
                    };
                }else{
                    this._store().openCursor().onsuccess = function (event) {
                        let cursor = event.target.result;
                        if (cursor) {
                            arr.push(Object.assign(cursor.value, {id: cursor.key}))
                            cursor.continue();
                        } else {
                            resolve(arr, event)
                        }
                    };
                }

            })
        }
        put = (data, key) => {
            return new Promise((resolve, reject) => {
                let request =  this._store('readwrite').put(data, key);
                request.onsuccess = e => resolve(e);
                request.onerror = e => reject(e);
            })
        }

        putList = list => {
            return this._recursion(list, this.put)
        }

        del = key => {
            return new Promise((resolve, reject) => {
                let request =  this._store('readwrite').delete(key);
                request.onsuccess = e => resolve(e);
                request.onerror = e => reject(e);
            })
        }

        delList = keyList => {
            return this._recursion(keyList, this.del)
        }

        clear = () => {
            this._store('readwrite').clear()
        }

        count = (key) => {
            return new Promise((resolve, reject) => {
                let request = this._store().count(key);
                request.onsuccess = e => resolve(e.target.result);
                request.onerror = e => reject(e);
            })
        }
    }
    w.DB = DB;

})(window);
